home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / btoa.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  28KB  |  1,115 lines

  1. /* btoa - binary to ascii    Authors: P. Rutter, J. Orost, & S. Parmark */
  2.  
  3. /*************************************************************************
  4.      Btoa is a filter which reads binary  bytes  from  the  input
  5.      file  and generates printable ASCII characters on the output
  6.      file. It attaches a header and a checksum to the archive. It
  7.      can  also  reverse  this,  creating  a  binary file from the
  8.      archive.
  9.  
  10.      Since last version of btoa/atob, several new  features  have
  11.      been  added.  The  most  obvious  one  is that atob has been
  12.      integrated with btoa. They are now the same program which is
  13.      called  with  different arguments. Another is the ability to
  14.      repair damaged archives.
  15.  
  16.      The new version is compatible with the old version, that is,
  17.      it can still encode and decode old btoa files.
  18.  
  19.      Btoa has an option to  decode  the  archive,  restoring  the
  20.      binary  bytes.   It  strips  the input file until it finds a
  21.      valid header, and continues decoding until the end  mark  is
  22.      found.  It  recognices  both old- and new-style headers, and
  23.      can decode both. It is possible to leave out the destination
  24.      name  when  decoding new-style archives, because the name is
  25.      stored in the header. Entering  a  name  will  override  the
  26.      autonaming function.
  27.  
  28.      It is possible to leave out  the  file  names  and  redirect
  29.      stdin and stdout with '<' and '>' to the desired files. This
  30.      is to maintain compatibility with earlier versions of btoa.
  31.  
  32.      Btoa now adds a single byte checksum  to  each  row  in  the
  33.      archive.   When  an  error is found, diagnosis automatically
  34.      starts and produces a diagnosis file which can  be  used  to
  35.      extract  the  damaged  part  from  an errorfree archive. The
  36.      extracted part can then  be  used  to  correct  the  damaged
  37.      archive.    Btoa  has  options  to  perform  the  reparation
  38.      automatically. This is especially  useful  when  downloading
  39.      data  converted to text files, and occasionally finding that
  40.      an archive file of considerable size turns is corrupted.
  41.  
  42. FEATURES
  43.      Btoa encodes 4 binary bytes into 5 characters, expanding the
  44.      file  by  25%. As a special case 4 zeroes will be encoded as
  45.      'z' and 4 spaces as 'y'. This makes it possible to  compress
  46.      the archive a bit.
  47.  
  48. EXAMPLES
  49.      Below follows a description  of  a  normal  repair  session.
  50.      Lines  beginning with 'Local>' were typed on the computer to
  51.      which the file was downloaded. Accordingly, lines  typed  on
  52.      the  connected computer will begin with 'Remote>'. Sending a
  53.      file to the other computer will be noted as 'transmit file'.
  54.  
  55.      A normal repairing procedure is as follows: Local>  btoa  -a
  56.      file.btoa  btoa:  Bad checksum on line 2648.  btoa: Starting
  57.      diagnosis.  btoa: Diagnosis output  to  'btoa.dia'.   Local>
  58.      transmit btoa.dia
  59.  
  60.      Remote> btoa -d file.btoa btoa: Repair output to 'btoa.rep'.
  61.      Remote> transmit btoa.rep
  62.  
  63.      Local> btoa -a btoa.rep btoa: Repaired  archive  written  to
  64.      'btoa.rdy'.
  65.  
  66.      You can now erase file.btoa and decode btoa.rdy using  'btoa
  67.      -a btoa.rdy'.
  68.  
  69. *************************************************************************/
  70.  
  71. #include <sys/types.h>
  72. #include <ctype.h>
  73. #include <string.h>
  74. #include <stdio.h>
  75.  
  76. #define MAXPERLINE      78
  77. #define BUFSIZE         100
  78. #define TRUE            1
  79. #define FALSE           0
  80. #define USE_MACROS      TRUE
  81.  
  82. #define BYTE            char
  83. #define WORD            short
  84. #define LONG            long
  85.  
  86. #define ENCODE(ch)      ( (int) ((ch) + '!') )
  87. #define DECODE(ch)      ( (int) ((ch) - '!') )
  88.  
  89. struct Diagnosis {
  90.   LONG startpos, endpos;    /* Line before and after erroneous area */
  91.   struct Diagnosis *next, *last;
  92. };
  93.  
  94. extern char *malloc();
  95.  
  96. /* Following functions have been converted to macros:  calcchecksum() */
  97.  
  98.  
  99. #if LATTICE            /* Prototypes for Lattice C */
  100.  
  101. void asciiout(int), exit(int),
  102.  intodiaglist(struct Diagnosis *, LONG, LONG),
  103.  outdiaglist(struct Diagnosis *, LONG *, LONG *), printhelp(void),
  104.  producediag(struct Diagnosis *, FILE *), wordout(LONG);
  105.  
  106. BYTE atob(FILE *), btoa(FILE *, BYTE *), copyfile(FILE *, FILE *, BYTE *),
  107.  decode_line(BYTE *, int), new_decodefile(FILE *, LONG *, LONG, int),
  108.  old_decodefile(FILE *, LONG *), performrepair(FILE *),
  109.  pro_repair(FILE *), readbuffer(BYTE *, BYTE *, FILE *),
  110. *truncname(BYTE *);
  111.  
  112. int nextbyte(FILE *);
  113.  
  114. FILE *fopen_read(BYTE *), *fopen_write(BYTE *);
  115.  
  116. #if USE_MACROS
  117. void calcchecksum(int);
  118. #endif /* USE_MACROS */
  119.  
  120. #else /* !LATTICE */    /* For compilers which don't know about prototypes. */
  121.  
  122. void asciiout(), exit(), intodiaglist(), outdiaglist(),
  123.  printhelp(), producediag(), wordout();
  124.  
  125. BYTE atob(), btoa(), copyfile(), decode_line(), new_decodefile(),
  126.  old_decodefile(), performrepair(), pro_repair(), readbuffer(),
  127. *truncname();
  128.  
  129. int nextbyte();
  130.  
  131. FILE *fopen_read(), *fopen_write();
  132.  
  133. #if USE_MACROS
  134. void calcchecksum();
  135. #endif /* USE_MACROS */
  136.  
  137. #endif /* LATTICE */
  138. /* Chksum.h */
  139. /* Calcchecksum() was converted to a macro for effectivity reasons. */
  140. /* Don't (!!) give it an argument that has to be evaluated. This    */
  141. /* Is guaranteed to slow it down.                                   */
  142.  
  143. /* Update file checksums. */
  144.  
  145. #define calcchecksum(ch)        \
  146. {                               \
  147.   extern LONG Ceor, Csum, Crot; \
  148.                                 \
  149.   Ceor ^= ch;                   \
  150.   Csum += ch + 1;               \
  151.                                 \
  152.   if (Crot & 0x80000000L)       \
  153.   {                             \
  154.     Crot <<= 1;                 \
  155.     Crot ++;                    \
  156.   }                             \
  157.   else                          \
  158.     Crot <<= 1;                 \
  159.                                 \
  160.   Crot += ch;                   \
  161. }
  162.  
  163. /* Btoa.c */
  164.  
  165. /* Written by Paul Rutter, Joe Orost & Stefan Parmark. */
  166.  
  167. #ifdef AMIGA
  168. #include <stdlib.h>
  169. #include <string.h>
  170. #endif /* AMIGA */
  171.  
  172.  
  173. #define VERSION  "5.2"
  174.  
  175. LONG Ceor, Csum, Crot;        /* Checksums to verify archive validity. */
  176. BYTE new_version, openoutput, buffer[BUFSIZE];
  177. FILE *outfile;
  178.  
  179.  
  180. void main(argc, argv)
  181. int argc;
  182. BYTE **argv;
  183. {
  184.   register BYTE openinput, error, ch, a_to_b, diag, repair;
  185.   register BYTE *infilename, *text;
  186.   register FILE *infile;
  187.   extern BYTE new_version, openoutput;
  188.   extern FILE *outfile;
  189. #ifdef AMIGA
  190.   extern int _bufsiz;
  191.  
  192.   /* Change file buffer size. */
  193.   _bufsiz = 10240;
  194. #endif /* AMIGA */
  195.  
  196.   error = openinput = openoutput = a_to_b = diag = repair = FALSE;
  197.   new_version = TRUE;
  198.   infilename = NULL;
  199.  
  200.   /* Scan for '-' options. The rest must be file names. */
  201.   while (!error && argc > 1 && *argv[1] == '-') {
  202.     text = &argv[1][1];
  203.     while (!error && (ch = *text++) != 0) {
  204.         switch (ch) {
  205.             case 'a':    /* Activate atob. */
  206.             a_to_b = TRUE;
  207.             break;
  208.             case 'd':    /* Extract missing part from
  209.                  * undamaged archive. */
  210.             diag = TRUE;
  211.             break;
  212.             case 'h':    /* Print help and abort execution. */
  213.             error = TRUE;
  214.             break;
  215.             case 'o':    /* Use old btoa format. */
  216.             new_version = FALSE;
  217.             break;
  218.             case 'r':    /* Repair damaged archive. */
  219.             repair = TRUE;
  220.             break;
  221.             default:    error = TRUE;
  222.         }
  223.     }
  224.     argv++;
  225.     argc--;
  226.   }
  227.  
  228.   if (argc > 3) error = TRUE;
  229.  
  230.   if (error)
  231.     printhelp();
  232.   else {
  233.     /* If file name was given, try to open file. Otherwise use stdin. */
  234.     if (argc > 1) {
  235.         infilename = argv[1];
  236.         if ((infile = fopen_read(infilename)) == NULL)
  237.             error = TRUE;
  238.         else
  239.             openinput = TRUE;
  240.     } else
  241.         infile = stdin;
  242.   }
  243.  
  244.   if (!error) {
  245.     /* If file name was given, try to open file. Otherwise use stdout. */
  246.     if (argc > 2 && !diag && !repair) {
  247.         if ((outfile = fopen_write(argv[2])) == NULL)
  248.             error = TRUE;
  249.         else
  250.             openoutput = TRUE;
  251.     } else
  252.         outfile = stdout;
  253.   }
  254.   if (!error) {
  255.     if (diag)
  256.         error = pro_repair(infile);
  257.     else if (repair)
  258.         error = performrepair(infile);
  259.     else if (a_to_b)
  260.         error = atob(infile);
  261.     else
  262.         error = btoa(infile, infilename);
  263.   }
  264.  
  265.   /* Close all opened files. */
  266.   if (openinput) fclose(infile);
  267.   if (openoutput) fclose(outfile);
  268.  
  269.   if (error) exit(1);
  270. }
  271.  
  272.  
  273. BYTE btoa(infile, infilename)
  274. register FILE *infile;
  275. register BYTE *infilename;
  276. {
  277.   register LONG codeword, fil